package com.xcity.game.activity.oneyuan.util;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xcity.db.entity.Build;
import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.db.entity.User;
import com.xcity.db.mapper.PlayerMapper;
import com.xcity.db.mapper.UserMapper;
import com.xcity.game.account.AccountChannel;
import com.xcity.game.build.BuildTemplate;
import com.xcity.game.common.GameStaticConfig;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.employee.EmployeeQuality;
import com.xcity.game.employee.EmployeeService;
import com.xcity.game.event.GameEvents;
import com.xcity.game.player.cache.PlayerCacheService;
import com.xcity.game.recharge.RechargeTemplate;
import com.xcity.util.DBUtils;

import gnu.trove.list.TLongList;
import gnu.trove.list.array.TLongArrayList;
import gnu.trove.set.TLongSet;
import gnu.trove.set.hash.TLongHashSet;
import naga.x.App;
import naga.x.common.Config;
import naga.x.common.Updatable;
import naga.x.event.Events;
import naga.x.game.template.TemplateService;
import naga.x.game.time.DayListener;
import naga.x.game.time.TimeUpdater;
import naga.x.util.CommonUtils;
import naga.x.util.IOUtils;
import naga.x.util.IOUtils.LineReaderListener;
import naga.x.util.StringUtils;
import naga.x.util.TimeUtils;
import naga.x.util.UUID;

public class RobotUtils implements Updatable, DayListener {

	static final Logger LOG = LoggerFactory.getLogger(RobotUtils.class);
	static List<String> NAMES = new ArrayList<String>();
	static List<String> ICONS = new ArrayList<String>();
	static List<BuildTemplate> BUILDS = new ArrayList<BuildTemplate>();
	static {
		BUILDS = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(BuildTemplate.class);
		BUILDS = new ArrayList<BuildTemplate>(BUILDS); // 避免shuffle之后打乱原始数据顺序
		String dir = App.getApp().getConfig().dataDir;//App.getApp().getConfig().getString(Config.DATA_DIR);
		File f = new File(dir, "tmp/robot.txt");
		IOUtils.read(f, IOUtils.UTF8, new LineReaderListener() {
			@Override
			public boolean readLine(String line) {
				line = StringUtils.trim(line);
				if (line.startsWith("http")) {
					ICONS.add(line);
				} else {
					NAMES.add(line);
				}
				return true;
			}
		});
	}
	public static RechargeTemplate RECHARGE_TEMPLATE;
	static int MAX_ROBOTS_SIZE = 50;
	static TLongList ROBOTIDS = new TLongArrayList(MAX_ROBOTS_SIZE);
	static TLongSet RECHARGED_ROBOT_IDS = new TLongHashSet();
	public static long fakePrizePlayerId;
	
	public static long create() {
		String name = NAMES.get(RND.nextInt(NAMES.size()));
		User acc = new User(name, User.DEAFULT_PASSWORD, "127.0.0.1", null);
		acc.setChannel(AccountChannel.OFFICIAL);
		acc.setChannelUid(UUID.randomUUID().toString());
		DBUtils.save(acc, UserMapper.class);
		LOG.info("[ROBOT ACCREG]ID[{}]NAME[{}]CHANNEL[{}]CID[{}]", acc.getId(), acc.getName(), acc.getChannel(), acc.getChannelUid());
		
		String icon = ICONS.get(RND.nextInt(ICONS.size()));
		Player player = new Player(acc.getId(), name, icon, RND.nextBoolean() ? Player.MALE : Player.FEMALE);
		player.setGold(GameStaticConfig.initGold);
		player.setStone(GameStaticConfig.initStone);
		player.poolSet(PlayerPool.PROPERTY_GUIDE, 60);
		DBUtils.save(player, PlayerMapper.class);
		player.init();

		EmployeeService es = App.getApp().getServiceManager().get(EmployeeService.class);
		int c = CommonUtils.randomInt(RND, 6, 10);
		CommonUtils.shuffle(BUILDS);
		while (c-- > 0) {
			BuildTemplate template = BUILDS.get(c);
//			String error = player.getBuildings().create(template.getId(), true);
//			if (error != null) {
				Build b = new Build(template.getId(), player.getBuildings());
				player.getBuildings().getBuildings().add(b);
				b.levelUp("ROBOT");
//			}
			int maxLvl = CommonUtils.randomInt(RND, 5, 25);
//			player.getBuildings().forceCompleteBuild("ROBOT");
//			Build b = player.getBuildings().getBuild(template.getId());
			while (b.getLevel() < maxLvl) {
				b.tryLevelUp();
				b.levelUp("ROBOT");
			}
			if (b.getLevel() > Build.BREAK_LEVEL && RND.nextBoolean()) {
				Employee e = es.configure().getTemplateConfigure().dropByQuality(player, EmployeeQuality.C, "ROBOT");
				if (e != null) {
					b.addEmployee(e, 0);
				}
			}
		}
		player.addGold(CommonUtils.randomInt(RND, 2000000, 10000000), "ROBOT");
		player.save();
		App.getApp().getEventManager().fireEvent(Events.EVENT_PLAYER_LOGOUT, player);
		synchronized (ROBOTIDS) {
			ROBOTIDS.add(player.getId());
		}
		LOG.info("[ROBOT REG]ID[{}]NAME[{}]SEX[{}]", player.getId(), player.getName(), player.getSex());
		return player.getId();
	}
	
	public static void doRecharge() {
		synchronized (ROBOTIDS) {
			if (ROBOTIDS.isEmpty()) {
				return;
			}
			long pid = ROBOTIDS.get(RND.nextInt(ROBOTIDS.size()));
//			Player player = App.getApp().getServiceManager().get(ActorService.class).find(pid);
			Player player = App.getApp().getServiceManager().get(PlayerCacheService.class).find(pid);
			if (player != null) {
				player.addStone(CommonUtils.randomInt(2, 10), "ROBOT");
				App.getApp().getEventManager().addEvent(GameEvents.EVENT_RECHARGE, player, 1, RECHARGE_TEMPLATE);
				RECHARGED_ROBOT_IDS.add(player.getId());
				LOG.info("[FAKE RECHARGE]ID[{}]RECHARGE[{}]", player.getId(), RECHARGE_TEMPLATE.getId());
			}
		}
	}
	
	public static long getFakePrizePlayer() {
		synchronized (ROBOTIDS) {
			if (!RECHARGED_ROBOT_IDS.isEmpty()) {
				long[] ids = RECHARGED_ROBOT_IDS.toArray();
				fakePrizePlayerId = ids[RND.nextInt(ids.length)];//ROBOTIDS.get(RND.nextInt(ROBOTIDS.size()));
			} else if (!ROBOTIDS.isEmpty()) {
				fakePrizePlayerId = ROBOTIDS.get(RND.nextInt(ROBOTIDS.size()));
			}
		}
		return fakePrizePlayerId;
	}
	
	public RobotUtils() {
		dayChanged();
		App.getApp().getUpdater().addAsync(this);
		TimeUpdater.getInstance().addDayListener(this);
	}
	
	static long timeFrom, timeEnd; // 假充值有效时间段
	static long nextFakeRechargeTime;
	static int todayMoney;
	static int todayTargetMoney; // 1400~1600
	static Random RND = new Random();
	static final int VALID_HOUR_FROM = 6, VALID_HOUR_TO = 24;
	static final int TIME_INTERVAL_MIN = 20000, TIME_INTERVAL_MAX = 90000;
	static final int FAKE_MONEY_MIN = 500, FAKE_MONEY_MAX = 1600;
	@Override
	public boolean update() {
		long now = TimeUpdater.getInstance().now();
		if (todayMoney < todayTargetMoney
				&& now >= nextFakeRechargeTime
				&& now >= timeFrom && now < timeEnd) {
			// 06:00~23:59 1~3rmb/min
			int n = CommonUtils.randomInt(RND, 1, 6);
			nextFakeRechargeTime = now + n * CommonUtils.randomInt(RND, TIME_INTERVAL_MIN, TIME_INTERVAL_MAX);
			while (n-- > 0) {
				doRecharge();
				if (++todayMoney >= todayTargetMoney) {
					getFakePrizePlayer();
					LOG.info("[FAKE RECHARGE PLAN DONE]TARGET[{}]TOTAL[{}]", todayTargetMoney, todayMoney);
					break;
				}
			}
		}
		return true;
	}

	@Override
	public boolean dayChanged() {
		long zeroTime = TimeUtils.getTodayZeroTime();
		todayMoney = 0;
		todayTargetMoney = CommonUtils.randomInt(RND, FAKE_MONEY_MIN, FAKE_MONEY_MAX);
		timeFrom = zeroTime + TimeUnit.HOURS.toMillis(VALID_HOUR_FROM);
		timeEnd = zeroTime + TimeUnit.HOURS.toMillis(VALID_HOUR_TO);
		nextFakeRechargeTime = timeFrom + CommonUtils.randomInt(RND, TIME_INTERVAL_MIN, TIME_INTERVAL_MAX);
		synchronized (ROBOTIDS) {
			RECHARGED_ROBOT_IDS.clear();
			if (ROBOTIDS.size() >= MAX_ROBOTS_SIZE) {
				ROBOTIDS.clear();
			}
			int n = CommonUtils.randomInt(RND, 10, MAX_ROBOTS_SIZE);
			while (n-- > 0) {
				create();
			}
		}
		getFakePrizePlayer();
		LOG.info("[FAKE RECHARGE PLAN]TARGET[{}]ROBOTS[{}]", todayTargetMoney, ROBOTIDS.size());
		return true;
	}

}
